package com.ruoyi.web.controller.teacher;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.domain.BasisPosition;
import com.ruoyi.domain.BasisUavTableDt;
import com.ruoyi.domain.PinpuInfo;
import com.ruoyi.service.*;
import com.ruoyi.service.impl.TcpClientServiceImpl;
import com.ruoyi.web.controller.student.MyDll;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@RestController
@RequestMapping("/tcpDt")
public class TcpDtController extends BaseController {

    @Autowired
    private TcpDtService tcpDtService;

    @Autowired
    private IBasisUavTableDtService iBasisUavTableDtService;


    @Autowired
    private TcpClientService tcpClientService;

    @Autowired
    private IBasisPositionService iBasisPositionService;

    private static  List<TcpClientServiceImpl.CSigSpec>  cachedValue;

    private static  List<double[]>  Alldata;

    private static List<double[]> zss ;

    @Autowired
    private IBasisTaskPlanService iBasisTaskPlanService;


    private static BasisPosition  basisPositionS;

    private static String retrunTimeS;

    @Autowired
    private IBasisPositionService basisPositionService;

    @GetMapping(value = "/selectByloadingId")
    public AjaxResult selectByloadingId(@RequestParam("loadingId")  String loadingId)
    {
        return success(tcpDtService.selectByloadingId(loadingId));
    }

    @GetMapping(value = "/selectFJByloadingId")
    public AjaxResult selectFJByloadingId(@RequestParam("loadingId")  String loadingId)
    {
        return success(tcpDtService.selectFJByloadingId(loadingId));
    }


    @GetMapping(value = "/getChartsInfo")
    public AjaxResult getChartsInfo(@RequestParam("loadingId")  String loadingId,@RequestParam("uavId")  String uavId,@RequestParam("time")  String time)
    {

        Map<String,Object> resultMap = new HashMap<String,Object>();
        List<BasisUavTableDt> basisUavTableDtList = iBasisUavTableDtService.selectBasisUavTableDtInfo(loadingId,uavId,time);
        if(basisUavTableDtList.size() != 0 ){
            BasisUavTableDt basisUavTableDt = basisUavTableDtList.get(0);

            //获取频谱的起止频率 和  最大最小频率
            String frequencyband = basisUavTableDt.getFrequencyband();
            int separatorIndex = frequencyband.indexOf("-");

            // 截取第一个时间
            String minPs = frequencyband.substring(0, separatorIndex);

            // 截取第二个时间
            String maxPs = frequencyband.substring(separatorIndex + 1);

            maxPs =  removeUnit(maxPs);
            PinpuInfo pinpuInfo = new PinpuInfo();
            double minP = Double.parseDouble(minPs);
            double maxP = Double.parseDouble(maxPs);
            double firstP = 0.0;
            double endP = 0.0;
            String ffrequencys = basisUavTableDt.getFrequency();
            double ffrequency = Double.parseDouble(ffrequencys);
            if(frequencyband.equals("118-137MHz") || frequencyband.equals("225-400MHz") || frequencyband.equals("243-270MHz") || frequencyband.equals("1626.5-1660.5MHz")){
                firstP = ffrequency - 5;
                endP = ffrequency +5;
            }else{
                firstP = ffrequency - 10;
                endP = ffrequency +10;
            }
            pinpuInfo.setMinP(minP);
            pinpuInfo.setEndP(endP);
            pinpuInfo.setFirstP(firstP);
            pinpuInfo.setMaxP(maxP);
            resultMap.put("basisUavTableDtInfo",basisUavTableDtList);
            resultMap.put("pinpuInfo",pinpuInfo);
        }else{
            resultMap.put("basisUavTableDtInfo","");
            resultMap.put("pinpuInfo","");
        }
        return success(resultMap);
    }

    public static  String removeUnit(String valueWithUnit) {
        // 使用正则匹配数字部分（包括小数点）
        Pattern pattern = Pattern.compile("([0-9]+\\.[0-9]+|[0-9]+)");
        Matcher matcher = pattern.matcher(valueWithUnit);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return valueWithUnit; // 如果没有匹配到数字，返回原字符串
    }

    private final MyDll dll = MyDll.INSTANCE;
    @GetMapping("/sendHand")
    public  List<double[]> sendHand(double min, double max,double startPort, double endPort, double longitude , double latitude,String loadingId,String caseName,Long positionId) throws IOException, ParseException {

        Long userid = getUserId();
        if(true){
            //查找阵地位置
            BasisPosition basisPosition = basisPositionService.selectBasisPositionById(positionId);
            basisPositionS = basisPosition;
            List<TcpClientServiceImpl.CSigSpec> cSigSpecList = tcpClientService.sendMessage(min,max,caseName,userid);
            cachedValue = cSigSpecList;


            double lengthAll = calculateDataPoints((int)min+"M", (int)max +"M");
            List<double[]> zs = new ArrayList<>();
            List<double[]> returnData = new ArrayList<>();
            //分不同的大小进行展示，逻辑不一样  全部的显示都是在[startPort,endPort],底噪数据
            // double startPort, double endPort
            List<double[]> generateNoiseData = generateNoiseData(startPort,endPort);

            for(TcpClientServiceImpl.CSigSpec cSigSpec : cSigSpecList){
                System.out.println("开始频点==="+cSigSpec.dbStartFreq);
                System.out.println("结束频点==="+cSigSpec.dbEndFreq);
                System.out.println("================================================");
                double firstS = cSigSpec.dbStartFreq;
                double firstD = firstS;
                float[] dataS = cSigSpec.fFFTData;
                Pointer inputPtr = new Memory(dataS.length * 4); // float占4字节
                inputPtr.write(0, dataS, 0, dataS.length);
                double longitude2 = Double.parseDouble(basisPosition.getLongitude());
                double latitude2 = Double.parseDouble(basisPosition.getLatitude());
                Pointer resultPtr = dll.FSPL(inputPtr,  dataS.length,
                        longitude, latitude, 500,
                        longitude2,  latitude2, 0,
                        (firstD + firstS)/2, 1);
                float[] callFSPL = resultPtr.getFloatArray(0, dataS.length);



                //判断返回的频段是否在区域内 如果频段的最大频率小于开始频段的舍弃不要  或者 频段的最小频率大于结束频率
                if(cSigSpec.dbEndFreq < startPort || cSigSpec.dbStartFreq > endPort) {

                }else{
                    for (int i = 0 ; i< callFSPL.length ;i++){
                        double[] doubles = new double[]{firstD, callFSPL[i]};
                        firstD = firstD + 0.001; // (最大值-最小值)/ lengthAll
                        firstD = round(firstD,3);
                        zs.add(doubles);
                    }
                }

            }
            zss = zs;
            // 替换逻辑

//            if(zs.size() > generateNoiseData.size()){
//                for(double[] item1 : zs) {
//                    for(int i = 0; i < generateNoiseData.size(); i++) {
//                        if(generateNoiseData.get(i)[0] == item1[0] && generateNoiseData.get(i)[1] < item1[1]) {
//                            generateNoiseData.set(i, item1);
//                            break;
//                        }
//                    }
//                }
//            }else if(zs.size() < generateNoiseData.size()){
//                for(int i = 0; i < generateNoiseData.size(); i++) {
//                    for(double[] item1 : zs) {
//                        System.out.println("");
//                        if(generateNoiseData.get(i)[0] == item1[0] && generateNoiseData.get(i)[1] < item1[1]) {
//                            System.out.println("ddddddddddddddddddd"+item1[0]+"-----------------"+item1[1]);
//                            generateNoiseData.set(i, item1);
//                            break;
//                        }
//                    }
//                }
//            }else{
            generateNoiseData =  replaceNoise(zs,generateNoiseData);
//                for(double[] item1 : zs) {
//                   // generateNoiseData.set(i, item1);
//                    generateNoiseData.add(Arrays.copyOf(item1, item1.length));
//                }
//            }


            Alldata = generateNoiseData;
            int ggi = 0;
            //double re = isFloorDifferenceGreaterThan20(endPort,startPort) ;
            if(isFloorDifferenceGreaterThan20(endPort,startPort) ) {
                for (int gg = 0; gg < generateNoiseData.size(); gg++) {

                    if (gg % 40 == 0 && gg != generateNoiseData.size() - 1) {
                        double[] doubles = generateNoiseData.get(gg);
                        returnData.add(doubles);
                    }
                    if (gg == generateNoiseData.size() - 1) {
                        double[] doubles = generateNoiseData.get(gg);
                        returnData.add(doubles);
                    }

                }
                return returnData;
            }else{
                return generateNoiseData;
            }
        }else{
            return null;
        }


    }



    @GetMapping("/getvalue2")
    public List<double[]> getValue2(double startPort, double endPort,double longitude , double latitude) throws IOException, ParseException {
        BasisPosition  basisPosition = basisPositionS;
        List<double[]> zs = new ArrayList<>();
        for(TcpClientServiceImpl.CSigSpec cSigSpec : cachedValue){
            System.out.println("开始频点==="+cSigSpec.dbStartFreq);
            System.out.println("结束频点==="+cSigSpec.dbEndFreq);
            System.out.println("================================================");
            double firstS = cSigSpec.dbStartFreq;
            double firstD = firstS;
            float[] dataS = cSigSpec.fFFTData;
            Pointer inputPtr = new Memory(dataS.length * 4); // float占4字节
            inputPtr.write(0, dataS, 0, dataS.length);
            double longitude2 = Double.parseDouble(basisPosition.getLongitude());
            double latitude2 = Double.parseDouble(basisPosition.getLatitude());
            Pointer resultPtr = dll.FSPL(inputPtr,  dataS.length,
                    longitude, latitude, 500,
                    longitude2,  latitude2, 0,
                    (firstD + firstS)/2, 1);
            float[] callFSPL = resultPtr.getFloatArray(0, dataS.length);



            //判断返回的频段是否在区域内 如果频段的最大频率小于开始频段的舍弃不要  或者 频段的最小频率大于结束频率
            if(cSigSpec.dbEndFreq < startPort || cSigSpec.dbStartFreq > endPort) {

            }else{
                for (int i = 0 ; i< callFSPL.length ;i++){
                    double[] doubles = new double[]{firstD, callFSPL[i]};
                    firstD = firstD + 0.001; // (最大值-最小值)/ lengthAll
                    firstD = round(firstD,3);
                    zs.add(doubles);
                }
            }

        }
        List<double[]> generateNoiseData = generateNoiseData(startPort, endPort);
        generateNoiseData = replaceNoise(zs, generateNoiseData);
        List<double[]> returnData = new ArrayList<>();
        if(isFloorDifferenceGreaterThan20(endPort,startPort) ) {
            for (int gg = 0; gg < generateNoiseData.size(); gg++) {

                if (gg % 40 == 0 && gg != generateNoiseData.size() - 1) {
                    double[] doubles = generateNoiseData.get(gg);
                    returnData.add(doubles);
                }
                if (gg == generateNoiseData.size() - 1) {
                    double[] doubles = generateNoiseData.get(gg);
                    returnData.add(doubles);
                }

            }
            return returnData;
        }else{
            return generateNoiseData;
        }
    }
    public static double calculateDataPoints(String startFreq, String endFreq) {
        long start = parseFrequency(startFreq);
        long end = parseFrequency(endFreq);
        if (start >= end) {
            throw new IllegalArgumentException("起始频率必须小于结束频率");
        }
        return (end - start) / 1000.0;
    }
    public static long parseFrequency(String freqStr) {
        freqStr = freqStr.toUpperCase();
        if (freqStr.endsWith("K")) {
            return Long.parseLong(freqStr.substring(0, freqStr.length()-1)) * 1000L;
        } else if (freqStr.endsWith("M")) {
            return Long.parseLong(freqStr.substring(0, freqStr.length()-1)) * 1000_000L;
        } else if (freqStr.endsWith("G")) {
            return Long.parseLong(freqStr.substring(0, freqStr.length()-1)) * 1000_000_000L;
        }
        return Long.parseLong(freqStr);
    }

    public static boolean isFloorDifferenceGreaterThan20(double a, double b) {
        // 计算差值并向下取整
        long flooredDiff = (long) Math.floor(Math.abs(a - b));
        return flooredDiff == 20;
    }

    public static List<double[]> replaceNoise(List<double[]> spectrumData, List<double[]> noiseData) {
        // 使用Map优化查找速度
        noiseData.forEach(noise -> {
            spectrumData.forEach(spectrum -> {
                if (spectrum[0] == noise[0] && spectrum[1] > noise[1]) {
                    noise[1] = spectrum[1];
                }
            });
        });
        return noiseData;
    }
    public static List<double[]> generateNoiseData(double min, double max) {
        List<double[]> result = new ArrayList<>();
        Random random = new Random();
        double length = calculateDataPoints((int)min+"M", (int)max+"M");
        double baseValue = -120; // 基础值
        double amplitude = 2; // 幅度

        // 创建二维数组
        double dd = min;
        for (int i = 0; i < length; i++) {
            double[] doubles = new double[]{ round(dd,3), baseValue + (random.nextDouble() * 2 * amplitude - amplitude)};
            dd = dd + ((int)max-(int)min)/length;
            result.add(doubles);
        }
        return result;
    }

    public static double round(double value, int places) {
        if (places < 0) {
            throw new IllegalArgumentException("小数位数不能为负数");
        }
        BigDecimal bd = BigDecimal.valueOf(value);
        bd = bd.setScale(places, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

}
